import 'package:intl/intl.dart';

class DateFormats {
  static String full = 'yyyy-MM-dd HH:mm:ss';
  static String y_mo_d_h_m = 'yyyy-MM-dd HH:mm';
  static String y_mo_d = 'yyyy-MM-dd';
  static String y_mo = 'yyyy-MM';
  static String mo_d = 'MM-dd';
  static String mo_d_h_m = 'MM-dd HH:mm';
  static String h_m_s = 'HH:mm:ss';
  static String h_m = 'HH:mm';

  static String zh_full = 'yyyy年MM月dd日 HH时mm分ss秒';
  static String zh_y_mo_d_h_m = 'yyyy年MM月dd日 HH时mm分';
  static String zh_y_mo_d = 'yyyy年MM月dd日';
  static String zh_y_mo = 'yyyy年MM月';
  static String zh_mo_d = 'MM月dd日';
  static String zh_mo_d_h_m = 'MM月dd日 HH时mm分';
  static String zh_h_m_s = 'HH时mm分ss秒';
  static String zh_h_m = 'HH时mm分';
}

class WhlDateUtils {
  /// month->days.
  static Map<int?, int> MONTH_DAY = {
    1: 31,
    2: 28,
    3: 31,
    4: 30,
    5: 31,
    6: 30,
    7: 31,
    8: 31,
    9: 30,
    10: 31,
    11: 30,
    12: 31,
  };

  /*根据年份获取周数*/
  static int numOfWeeks(int year) {
    DateTime dec28 = DateTime(2022, 12, 28);
    int dayOfDec28 = int.parse(DateFormat("D").format(dec28));
    return ((dayOfDec28 - dec28.weekday + 10) / 7).floor();
  }

  /*根据日期获取在当年的第几周*/
  static int weekNumber(DateTime date) {
    int dayOfYear = int.parse(DateFormat("D").format(date));
    int woy = ((dayOfYear - date.weekday + 10) / 7).floor();
    if (woy < 1) {
      woy = numOfWeeks(date.year - 1);
    } else if (woy > numOfWeeks(date.year)) {
      woy = 1;
    }
    return woy;
  }

  /* 根据第几周获取开始时间和结束时间*/
  static Map<String, String> getDateTimeStringFromWeekNumber({required int year, required int weekNumber}) {
    int firstDayOfWeek = (weekNumber - 1) * 7;
    final extraDuration = Duration(days: firstDayOfWeek);

    final startDate = DateTime(year);
    Map<String, String> dateMap = {};
    final dates = startDate.add(extraDuration);
    DateTime? startTime;
    for (var i = 0; i < 8; i++) {
      var newDate = dates.add(Duration(days: i));
      if (DateFormat('EEEE').format(newDate) == 'Monday') {
        startTime = newDate;
        // dateMap.addAll({'startTime': newDate.toString()});
      } else if (DateFormat('EEEE').format(newDate) == 'Sunday') {
        // dateMap.addAll({'endTime': newDate.toString()});
      }
    }
    DateTime endTime = startTime!.add(const Duration(days: 6));
    endTime = endTime.add(const Duration(seconds: 86399));
    dateMap['endTime'] = DateFormat('yyyy-MM-dd HH:mm:ss').format(endTime);
    dateMap['startTime'] = DateFormat('yyyy-MM-dd HH:mm:ss').format(startTime);
    return dateMap;
  }

  static DateTime getMondayTimeFromDate(DateTime date) {
    int week = weekNumber(date);
    Map<String, String> map = getDateTimeStringFromWeekNumber(year: date.year, weekNumber: week);
    return DateFormat('yyyy-MM-dd HH:mm:ss').parse(map['startTime'] ?? '');
  }

  static String getEndMoth(int timeSamp, {format = "yyyy-MM-dd HH:mm:ss"}) {
    var dateFormat = DateFormat(format);
    var dateTime = DateTime.fromMillisecondsSinceEpoch(timeSamp);
    var dateNextMonthDate = DateTime(dateTime.year, dateTime.month + 1, 1);
    int nextTimeSamp = dateNextMonthDate.millisecondsSinceEpoch - 24 * 60 * 60 * 1000;
    //取得了下一个月1号码时间戳
    var dateTimeeee = DateTime.fromMillisecondsSinceEpoch(nextTimeSamp);
    dateTimeeee = dateTimeeee.add(Duration(seconds: 86399));
    String formartResult = dateFormat.format(dateTimeeee);
    return formartResult;
  }

  static String getDateScope({required checkDate}) {
    String temp = DateTime.now().toString();
    List listTemp = temp.split(" ");
    temp = listTemp[0];
    DateTime nowTime = DateTime.parse(temp);
    DateTime checkTime = DateTime.fromMillisecondsSinceEpoch(checkDate);

    Duration diff = checkTime.difference(nowTime);

    ///如果不同年 返回 年-月-日 小时:分钟 不显示秒及其.000
    if (checkTime.year != nowTime.year) {
      return checkTime.toString().substring(0, checkTime.toString().length - 7);
    }

    /// 同年判断是不是前天/昨天/今天/
    if ((diff < const Duration(hours: 24)) && (diff > const Duration(hours: 0))) {
      return "今天";
    } else if ((diff < const Duration(hours: 0)) && (diff > const Duration(hours: -24))) {
      return "昨天";
    } else if (diff < const Duration(hours: -24) && diff > const Duration(hours: -48)) {
      return "前天";
    }

    ///如果剩下都不是就返回 月-日 然后时间
    return checkTime.toString().substring(5, checkTime.toString().length - 7);
  }

  static String getDateFormat(int timeSamp) {
    int temp = DateTime.now().millisecondsSinceEpoch - timeSamp;
    if (temp > 7 * 24 * 60 * 60 * 1000) {
      return DateFormat('yyyy-MM-dd').format(DateTime.fromMillisecondsSinceEpoch(timeSamp));
    } else if (temp > 24 * 60 * 60 * 1000) {
      return '${(temp / (24 * 60 * 60 * 1000)).floor()}天前';
    } else if (temp > 60 * 60 * 1000) {
      return '${(temp / (60 * 60 * 1000)).floor()}小时前';
    } else if (temp > 60 * 1000) {
      return '${(temp / (60 * 1000)).floor()}分钟前';
    } else {
      return '刚刚';
    }
  }

  static String getTimeStringFromWechat(
    int ms, {
    int? locMs,
    String formatToday = 'HH:mm',
    String format = 'yyyy-MM-dd',
    String languageCode = 'en',
    bool short = false,
    bool isShowTime = true,
  }) {
    int _locTimeMs = locMs ?? DateTime.now().millisecondsSinceEpoch;
    int elapsed = _locTimeMs - ms;
    if (elapsed < 0) {
      return DateFormat(formatToday).format(DateTime.fromMillisecondsSinceEpoch(ms));
    }

    if (isToday(ms, locMs: _locTimeMs)) {
      return DateFormat(formatToday).format(DateTime.fromMillisecondsSinceEpoch(ms));
    }

    // if (isYesterdayByMs(ms, _locTimeMs)) {
    //   return languageCode == 'zh'
    //       ? isShowTime
    //           ? '昨天 ${formatDateMs(ms, format: formatToday)}'
    //           : '昨天'
    //       : 'Yesterday';
    // }

    // if (isWeek(ms, locMs: _locTimeMs)) {
    //   return isShowTime
    //       ? '${getWeekdayByMs(ms, languageCode: languageCode, short: short)}  ${formatDateMs(ms, format: formatToday)}'
    //       : getWeekdayByMs(ms, languageCode: languageCode, short: short);
    // }

    return isShowTime ? '${formatDateMs(ms, format: format)}  ${formatDateMs(ms, format: formatToday)}' : formatDateMs(ms, format: format);
  }

  /// is today.
  /// 是否是当天.
  static bool isToday(int milliseconds, {bool isUtc = false, required int locMs}) {
    if (milliseconds == null || milliseconds == 0) return false;
    DateTime old = DateTime.fromMillisecondsSinceEpoch(milliseconds, isUtc: isUtc);
    DateTime now;
    if (locMs != null) {
      now = DateTime.fromMillisecondsSinceEpoch(locMs);
    } else {
      now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
    }
    return old.year == now.year && old.month == now.month && old.day == now.day;
  }

  static bool isYesterdayByMs(int ms, int locMs) {
    return isYesterday(DateTime.fromMillisecondsSinceEpoch(ms), DateTime.fromMillisecondsSinceEpoch(locMs));
  }

  /// is yesterday by dateTime.
  /// 是否是昨天.
  static bool isYesterday(DateTime dateTime, DateTime locDateTime) {
    if (yearIsEqual(dateTime, locDateTime)) {
      int spDay = getDayOfYear(locDateTime) - getDayOfYear(dateTime);
      return spDay == 1;
    } else {
      return ((locDateTime.year - dateTime.year == 1) &&
          dateTime.month == 12 &&
          locDateTime.month == 1 &&
          dateTime.day == 31 &&
          locDateTime.day == 1);
    }
  }

  /// year is equal.
  /// 是否同年.
  static bool yearIsEqual(DateTime dateTime, DateTime locDateTime) {
    return dateTime.year == locDateTime.year;
  }

  /// get day of year.
  /// 在今年的第几天.
  static int getDayOfYear(DateTime dateTime) {
    int year = dateTime.year;
    int month = dateTime.month;
    int days = dateTime.day;
    for (int i = 1; i < month; i++) {
      int index = MONTH_DAY[i] ?? 0;
      days = days + index;
    }
    if (isLeapYearByYear(year) && month > 2) {
      days = days + 1;
    }
    return days;
  }

  /// Return whether it is leap year.
  /// 是否是闰年
  static bool isLeapYearByYear(int year) {
    return year % 4 == 0 && year % 100 != 0 || year % 400 == 0;
  }

  static bool isWeek(int ms, {bool isUtc = false, int? locMs}) {
    if (ms == null || ms <= 0) {
      return false;
    }
    DateTime _old = DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc);
    DateTime _now;
    if (locMs != null) {
      _now = DateTime.fromMillisecondsSinceEpoch(locMs, isUtc: isUtc);
    } else {
      _now = isUtc ? DateTime.now().toUtc() : DateTime.now().toLocal();
    }

    DateTime old = _now.millisecondsSinceEpoch > _old.millisecondsSinceEpoch ? _old : _now;
    DateTime now = _now.millisecondsSinceEpoch > _old.millisecondsSinceEpoch ? _now : _old;
    return (now.millisecondsSinceEpoch - old.millisecondsSinceEpoch <= 7 * 24 * 60 * 60 * 1000);
  }

  /// get WeekDay By Milliseconds.
  static String getWeekdayByMs(int milliseconds, {bool isUtc = false, String languageCode = 'en', bool short = false}) {
    DateTime dateTime = getDateTimeByMs(milliseconds, isUtc: isUtc);
    return getWeekday(dateTime, languageCode: languageCode, short: short);
  }

  /// get DateTime By Milliseconds.
  static DateTime getDateTimeByMs(int ms, {bool isUtc = false}) {
    return DateTime.fromMillisecondsSinceEpoch(ms, isUtc: isUtc);
  }

  /// format date by milliseconds.
  /// milliseconds 日期毫秒
  static String formatDateMs(int ms, {bool isUtc = false, String? format}) {
    return formatDate(getDateTimeByMs(ms, isUtc: isUtc), format: format);
  }

  /// format date by DateTime.
  /// format 转换格式(已提供常用格式 DateFormats，可以自定义格式：'yyyy/MM/dd HH:mm:ss')
  /// 格式要求
  /// year -> yyyy/yy   month -> MM/M    day -> dd/d
  /// hour -> HH/H      minute -> mm/m   second -> ss/s
  static String formatDate(DateTime dateTime, {String? format}) {
    if (dateTime == null) return '';
    format = format ?? DateFormats.full;
    if (format.contains('yy')) {
      String year = dateTime.year.toString();
      if (format.contains('yyyy')) {
        format = format.replaceAll('yyyy', year);
      } else {
        format = format.replaceAll('yy', year.substring(year.length - 2, year.length));
      }
    }

    format = _comFormat(dateTime.month, format, 'M', 'MM');
    format = _comFormat(dateTime.day, format, 'd', 'dd');
    format = _comFormat(dateTime.hour, format, 'H', 'HH');
    format = _comFormat(dateTime.minute, format, 'm', 'mm');
    format = _comFormat(dateTime.second, format, 's', 'ss');
    format = _comFormat(dateTime.millisecond, format, 'S', 'SSS');

    return format;
  }

  /// com format.
  static String _comFormat(int value, String format, String single, String full) {
    if (format.contains(single)) {
      if (format.contains(full)) {
        format = format.replaceAll(full, value < 10 ? '0$value' : value.toString());
      } else {
        format = format.replaceAll(single, value.toString());
      }
    }
    return format;
  }

  /// get WeekDay.
  /// dateTime
  /// isUtc
  /// languageCode zh or en
  /// short
  static String getWeekday(DateTime dateTime, {String languageCode = 'en', bool short = false}) {
    if (dateTime == null) return "";
    String weekday = "";
    switch (dateTime.weekday) {
      case 1:
        weekday = languageCode == 'zh' ? '星期一' : 'Monday';
        break;
      case 2:
        weekday = languageCode == 'zh' ? '星期二' : 'Tuesday';
        break;
      case 3:
        weekday = languageCode == 'zh' ? '星期三' : 'Wednesday';
        break;
      case 4:
        weekday = languageCode == 'zh' ? '星期四' : 'Thursday';
        break;
      case 5:
        weekday = languageCode == 'zh' ? '星期五' : 'Friday';
        break;
      case 6:
        weekday = languageCode == 'zh' ? '星期六' : 'Saturday';
        break;
      case 7:
        weekday = languageCode == 'zh' ? '星期日' : 'Sunday';
        break;
      default:
        break;
    }
    return languageCode == 'zh' ? (short ? weekday.replaceAll('星期', '周') : weekday) : weekday.substring(0, short ? 3 : weekday.length);
  }
}
